#cs ----------------------------------------------------------------------------

 AutoIt Version: 3.3.8.1
 Author:         Dave Fulghan

 Script Function:
	Installed programs browser

#ce ----------------------------------------------------------------------------

; Script Start - Add your code below here

#include <ButtonConstants.au3>
#include <GUIConstantsEx.au3>
#include <ListViewConstants.au3>
#include <GuiListView.au3>
#include <WindowsConstants.au3>
Dim $nCol, $nColumn, $bSet, $nSortDir, $nCurCol, $nColAdjust, $uninstallString, $liIndex
Dim $changesSize = 16
Dim $changes[$changesSize][3]
Dim $changeTop = 0
Enum $initial, $checkclick

Opt("GUIOnEventMode", 1)
#Region ### START Koda GUI section ### Form=C:\Users\Dave\Desktop\Devel\Koda\Forms\Unwanted.kxf
$Form1 = GUICreate("Form1", 604, 248, 206, 124)
$ListView1 = GUICtrlCreateListView("|Program|Publisher|Uninstall|cheat", 0, 0, 601, 217, -1, BitOR($WS_EX_CLIENTEDGE,$LVS_EX_CHECKBOXES, $LVS_SORTASCENDING))
$ListView1context = GUICtrlCreateContextMenu($ListView1)
$MenuTop = GUICtrlCreateMenuItem("Send to Top", $ListView1context)
GUICtrlSetOnEvent($MenuTop, "MenuTopClick")
$MenuBottom = GUICtrlCreateMenuItem("Send to Bottom", $ListView1context)
GUICtrlSetOnEvent($MenuBottom, "MenuBottomClick")
$UninstallButton = GUICtrlCreateButton("Uninstall", 496, 218, 105, 25)
$Checkbox1 = GUICtrlCreateCheckbox("Hide Updates", 16, 218, 89, 25)
$Checkbox2 = GUICtrlCreateCheckbox("Hide all Microsoft", 120, 218, 121, 25)
#EndRegion ### END Koda GUI section ###

GUISetOnEvent($GUI_EVENT_CLOSE, "SpecialEvents")
GUISetOnEvent($GUI_EVENT_MINIMIZE, "SpecialEvents")
GUISetOnEvent($GUI_EVENT_RESTORE, "SpecialEvents")
;GUIRegisterMsg($WM_GETMINMAXINFO, "MY_WM_GETMINMAXINFO")
GUIRegisterMsg($WM_NOTIFY, "WM_NOTIFY") ;This intercepts the Notification windows sends your GUI when you right click the listview (and many others) amd sends it to the "WM_NOTIFY" function.


GUICtrlSetOnEvent($ListView1, "ListViewClick")
GUICtrlSetOnEvent($Checkbox1, "RefreshList")
GUICtrlSetOnEvent($Checkbox2, "RefreshList")
GUICtrlRegisterListViewSort($ListView1, "LVSort")
$nCol = 5
GUICtrlSetOnEvent($UninstallButton, "Uninstall")

PopulateList($initial)

GUISetState(@SW_SHOW)

While 1
	Sleep(100)
WEnd

Func MenuAddlClick()

EndFunc

Func SpecialEvents()
    Select
        Case @GUI_CtrlId = $GUI_EVENT_CLOSE
            ;MsgBox(0, "Close Pressed", "ID=" & @GUI_CtrlId & " WinHandle=" & @GUI_WinHandle)
            Exit

        Case @GUI_CtrlId = $GUI_EVENT_MINIMIZE
            ;MsgBox(0, "Window Minimized", "ID=" & @GUI_CtrlId & " WinHandle=" & @GUI_WinHandle)

        Case @GUI_CtrlId = $GUI_EVENT_RESTORE
            ;MsgBox(0, "Window Restored", "ID=" & @GUI_CtrlId & " WinHandle=" & @GUI_WinHandle)

    EndSelect
EndFunc   ;==>SpecialEvents

Func ListItemClick()
	MsgBox(0, "Debug - ListItemClick", GUICtrlRead(@GUI_CtrlId, 1) & @CRLF & "$GUI_CHECKED is:" & GUICtrlRead(@GUI_CtrlId, 1))

	Local $checkState = GUICtrlRead(@GUI_CtrlId, 1)
	If $checkState == 1 Then
		GUICtrlSetData(@GUI_CtrlId, "||||555")
	Else
		GUICtrlSetData(@GUI_CtrlId, "||||")
	EndIf

	If $changeTop > 0 Then
		For $step = 0 To $changeTop - 1
			If $changes[$step][0] = @GUI_CtrlId Then
				$changes[$step][2] = $checkState
				GUICtrlSetState($UninstallButton, $GUI_ENABLE)
				Return
			EndIf
		Next
		If $checkState == 1 Then
			If $changeTop >= $changesSize Then
				$changesSize = $changesSize + 16
				ReDim $changes[$changesSize][3]
			EndIf
			$changes[$changeTop][0] = @GUI_CtrlId
			$changes[$changeTop][1] = GUICtrlRead(@GUI_CtrlId, 0) ; Text from columns
			$changes[$changeTop][2] = $checkState ; State of checkbox
			;MsgBox(0, "Debug", "Changetop is: " & $changeTop & " wrote:" & @CRLF & $changes[$changeTop][1])
			$changeTop = $changeTop + 1
		EndIf
	ElseIf $checkState == 1 Then
		$changes[0][0] = @GUI_CtrlId
		$changes[0][1] = GUICtrlRead(@GUI_CtrlId, 0) ; Text from columns
		$changes[0][2] = $checkState ; State of checkbox
		$changeTop = 1
	EndIf
	GUICtrlSetState($UninstallButton, $GUI_ENABLE)
EndFunc

Func ListViewClick()
	;MsgBox(0, "Debug","")
	$bSet = 0
	$nCurCol = $nCol
EndFunc

Func LVSort($hWnd, $nItem1, $nItem2, $nColumn)
	;MsgBox(0, "Debug", "Call LVSort")
    Local $nSort, $val1, $val2, $nResult

    ; Switch the sorting direction
    If $nColumn = $nCurCol Then
        If Not $bSet Then
			;MsgBox(0, "Debug - nResult:", "Flip sort dir")
            $nSortDir = $nSortDir * -1
            $bSet = 1
        EndIf
    Else
        $nSortDir = 1
		If $nColumn = 0 Then
			$nColAdjust = 4
		Else
			$nColAdjust = 0
		EndIf
    EndIf
	;$nSortDir = $nSortDir * -1
    $nCol = $nColumn

    $val1 = GetSubItemText($hWnd, $nItem1, $nColumn + $nColAdjust)
    $val2 = GetSubItemText($hWnd, $nItem2, $nColumn + $nColAdjust)

    ; If it is the 3rd colum (column starts with 0) then compare the dates
    ;If $nColumn = 2 Then
    ;   $val1 = StringMid($val1, 2, 8)
     ;   $val2 = StringMid($val2, 2, 8)
    ;EndIf

    $nResult = 0    ; No change of item1 and item2 positions

    If $val1 < $val2 Then
        $nResult = -1   ; Put item2 before item1
    ElseIf $val1 > $val2 Then
        $nResult = 1    ; Put item2 behind item1
    EndIf

    $nResult = $nResult * $nSortDir
;	MsgBox(0, "Debug - nResult:", $nResult)

    Return $nResult
EndFunc

Func Uninstall()
	Local $verifyMsg = "You have chosen to uninstall these programs:" & @CRLF
	For $step = 0 to $changeTop - 1
		If $changes[$step][2] == 1 Then
			$ourMatches = StringRegExp($changes[$step][1], '\|(.*?)\|', 1)
			;MsgBox(0, "Debug", "Array sized is: " & UBound($ourMatches) & @CRLF & $changes[$step][1])
			$verifyMsg = $verifyMsg & "  " & $ourMatches[0] & @CRLF
		EndIf
	Next
	$verifyMsg &= "Do you wish to perform these uninstalls?"
	$ourAnswer = MsgBox(4, "Confirm:", $verifyMsg)
	If $ourAnswer = 6 Then
		For $step = 0 to $changeTop - 1
			If $changes[$step][2] == 1 Then
				Local $ourSplit = StringSplit($changes[$step][1],"|")

				MsgBox(0, "Debug", $ourSplit[4])
				RunWait($ourSplit[4])
			EndIf
		Next
	EndIf
EndFunc


Func GetSubItemText($nCtrlID, $nItemID, $nColumn)
    Local $stLvfi = DllStructCreate("uint;ptr;int;int[2];int")
    Local $nIndex, $stBuffer, $stLvi, $sItemText

    DllStructSetData($stLvfi, 1, $LVFI_PARAM)
    DllStructSetData($stLvfi, 3, $nItemID)

    $stBuffer = DllStructCreate("char[260]")

    $nIndex = GUICtrlSendMsg($nCtrlID, $LVM_FINDITEM, -1, DllStructGetPtr($stLvfi));

    $stLvi = DllStructCreate("uint;int;int;uint;uint;ptr;int;int;int;int")

    DllStructSetData($stLvi, 1, $LVIF_TEXT)
    DllStructSetData($stLvi, 2, $nIndex)
    DllStructSetData($stLvi, 3, $nColumn)
    DllStructSetData($stLvi, 6, DllStructGetPtr($stBuffer))
    DllStructSetData($stLvi, 7, 260)

    GUICtrlSendMsg($nCtrlID, $LVM_GETITEMA, 0, DllStructGetPtr($stLvi));

    $sItemText = DllStructGetData($stBuffer, 1)

    $stLvi = 0
    $stLvfi = 0
    $stBuffer = 0

    Return $sItemText
EndFunc   ;==>GetSubItemText

Func PopulateList($operation)
	Local $ourWalk
	If (Not $operation = $initial) Then
		;_GUICtrlListView_DeleteAllItems($ListView1)
		_GUICtrlListView_Scroll($ListView1, 0, -3500)
		_GUICtrlListView_DeleteAllItems($ListView1)
		;_GUICtrlListView_DeleteItemsSelected($ListView1)
		;_GUICtrlListView_AddItem($ListView1, "Program|Publisher|Uninstall|cheat")
		;GUICtrlSetData($ListView1, "|Program|Publisher|Uninstall|cheat")
		;GUICtrlCreateListViewItem("|choo|cjoo|choo", $ListView1)
		;MsgBox(0, "debug", "Clearing")
	EndIf
	Local $noms = GUICtrlRead($Checkbox2)
	Local $noupdates = GUICtrlRead($Checkbox1)


	While 1
		$ourWalk = $ourWalk +1
		$ourCLSID = RegEnumKey("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", $ourWalk)
		If @error Then ExitLoop
		$friendlyName = RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" & $ourCLSID, "DisplayName")
		$pubName = RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" & $ourCLSID, "Publisher")
		If ($noms = $GUI_CHECKED) And (StringInStr($pubName, "Microsoft Corporation") Or StringInStr($pubName, "Microsoft")) Then ContinueLoop
		If ($noupdates = $GUI_CHECKED) And (StringInStr($friendlyName, "(KB") Or StringInStr($friendlyName, "(SP")) Then ContinueLoop
		$uninstallString = RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" & $ourCLSID, "UninstallString")
		If $friendlyName Then
			$ourLine = GUICtrlCreateListViewItem("|" & $friendlyName & "|" & $pubName & "|" & $uninstallString, $ListView1)
			GUICtrlSetOnEvent($ourLine, "ListItemClick")
			;If ( ) Then
			;	GUICtrlSetState($ourLine, $GUI_CHECKED)
			;	GUICtrlSetData($ourLine, "|||a")
			;EndIf
		EndIf
	WEnd
EndFunc

Func RefreshList()
	PopulateList($checkclick)
EndFunc

;All Notify messages for your GUI will be send to this function.
Func WM_NOTIFY($hWnd, $iMsg, $iwParam, $ilParam)
    #forceref $hWnd, $iMsg, $iwParam
    Local $hWndFrom, $iIDFrom, $iCode, $tNMHDR, $hWndListView, $tInfo

    If Not IsHWnd($ListView1) Then $hWndListView = GUICtrlGetHandle($ListView1)

    ;$ilParam is a pointer. This reads what's at that adress. (not sure why the name suggests its an int)
    $tNMHDR = DllStructCreate($tagNMHDR, $ilParam)
    $hWndFrom = HWnd(DllStructGetData($tNMHDR, "hWndFrom"))
   
    $iIDFrom = DllStructGetData($tNMHDR, "IDFrom")
    $iCode = DllStructGetData($tNMHDR, "Code")

    Switch $hWndFrom ;Check what control triggered the msg
        Case $hWndListView ;If it was the listview...
            Switch $iCode ;Check what action triggered the msg
			   Case $NM_RCLICK ;If it was a right click...
					 MsgBox(0, "Debug", "Got right click" & @CRLF & "HWnd:" & $hWnd & @CRLF & "iMsg:" & $iMsg & @CRLF & "ilParam:" & $ilParam)
                    $tInfo = DllStructCreate($tagNMITEMACTIVATE, $ilParam) ;get the information about the item clicked.
					$liIndex = DllStructGetData($tInfo, "Index")
					;$hListItem = DllStructGetData($tInfo, "Index")
                    ;$sItemText =  _GUICtrlListView_GetItemText($hWndListView, DllStructGetData($tInfo, "Index"), DllStructGetData($tInfo, "SubItem")) ;store the item text in a global variable in case the get text option is clicked.
                    ;You could also just store the Index and SubItem values, the entire $tInfo struct, or whatever works best for you.

                    ;Uncomment the next part to get more information about your click.
                 _DebugPrint("$NM_RCLICK" & @LF & "--> hWndFrom:" & @TAB & $hWndFrom & @LF & _
                         "-->IDFrom:" & @TAB & $iIDFrom & @LF & _
                         "-->Code:" & @TAB & $iCode & @LF & _
                         "-->Index:" & @TAB & DllStructGetData($tInfo, "Index") & @LF & _
                         "-->SubItem:" & @TAB & DllStructGetData($tInfo, "SubItem") & @LF & _
                         "-->NewState:" & @TAB & DllStructGetData($tInfo, "NewState") & @LF & _
                         "-->OldState:" & @TAB & DllStructGetData($tInfo, "OldState") & @LF & _
                         "-->Changed:" & @TAB & DllStructGetData($tInfo, "Changed") & @LF & _
                         "-->ActionX:" & @TAB & DllStructGetData($tInfo, "ActionX") & @LF & _
                         "-->ActionY:" & @TAB & DllStructGetData($tInfo, "ActionY") & @LF & _
                         "-->lParam:" & @TAB & DllStructGetData($tInfo, "lParam") & @LF & _
                        "-->KeyFlags:" & @TAB & DllStructGetData($tInfo, "KeyFlags"))

            EndSwitch
        EndSwitch

    ;Returning this allows the GUI to handle the messages in the usual way once you're done. Returning anything else will block default behavior. (giving you a largely unresponsive GUI)
    Return $GUI_RUNDEFMSG
 EndFunc
 
 Func MenuTopClick()
	MsgBox(0, "Debug", $liIndex)
 EndFunc
 
 Func _DebugPrint($s_text, $line = @ScriptLineNumber)
    ConsoleWrite( _
            "!===========================================================" & @LF & _
            "+======================================================" & @LF & _
            "-->Line(" & StringFormat("%04d", $line) & "):" & @TAB & $s_text & @LF & _
            "+======================================================" & @LF)
EndFunc
 